﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PluggableModulesInterface;
using SMSROUTER.Business;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using Utils;
using StorageManagement;
using Settings;
using System.Xml;
using System.IO;
using PluggableModulesRouter;
using SMSROUTER.StorageManagement;

namespace MTRouterVinaphoneBulkSms
{
    public class VinaPhoneRouter : WorkingBaseMTHttpRouter
    {
        #region Properties and Fields
        public string UserName
        {
            get
            {
                return GetConfig("UserName");
            }
            set
            {
                SetConfig("UserName", value);
            }
        }
        public string Password
        {
            get
            {
                return GetConfig("Password");
            }
            set
            {
                SetConfig("Password", value);
            }
        }

        public int DefaultMTTypeID
        {
            get
            {
                return int.Parse(GetConfig("DefaultMTTypeID"));
            }
            set
            {
                SetConfig("DefaultMTTypeID", value.ToString());
            }
        }
        #endregion

        public VinaPhoneRouter()
            : base()
        {
            SmsRouterObject.ContentType = "text/xml;charset=UTF-8";
        }

        protected override void SendSms(List<SmsOutWaiting> smsOutWaitingList)
        {
            int threadId = ThreadID;
            bool logToText = this.EnableLogToText;
            foreach (var item in smsOutWaitingList)
            {
                try
                {
                    string strxml = "", strException = "";
                    string smsSentType = "", errorCode = "", errorDesc = "";
                    if (CreateXmlOject(item, ref strxml, ref strException))
                    {
                        string result = SmsRouterObject.Execute(strxml, "POST");
                        
                        if (!string.IsNullOrEmpty(result))
                        {
                            ResponseXMLParser(result, ref smsSentType, ref errorCode, ref errorDesc);
                            if (errorCode == "0")
                            {
                                SmsOutReportStorage.EnqueueElementData(Key, new SmsOutReportStruct(item.RouterID, item.SmsOutGUID, item.CooperateGUID, DateTime.Now, DateTime.Now, item.RetryOnFailReqTimes, item.RetryOnTimeOutReqTimes, AppSetting.Status.SENT, threadId));
                            }
                            else
                            {
                                SmsOutReportStorage.EnqueueElementData(Key, new SmsOutReportStruct(item.RouterID, item.SmsOutGUID, item.CooperateGUID, DateTime.Now, DateTime.Now, item.RetryOnFailReqTimes, item.RetryOnTimeOutReqTimes, AppSetting.Status.FAIL, threadId));
                                Log.InsertLog(string.Format("[SmsOutGUID = {0}] erorr: Nhận được trả lời từ respone: {1}", item.SmsOutGUID, errorDesc), "SendSms", ObjectType, AppSetting.WarningType.mt_error, item.CooperateID);
                            }
                        }
                        else
                        {
                            //Gửi không thành công do không nhận được respone
                            SmsOutReportStorage.EnqueueElementData(Key, new SmsOutReportStruct(item.RouterID, item.SmsOutGUID, item.CooperateGUID, DateTime.Now, DateTime.Now, item.RetryOnFailReqTimes, item.RetryOnTimeOutReqTimes, AppSetting.Status.FAIL, threadId));
                            Log.InsertLog(string.Format("[SmsOutGUID = {0}] erorr: Gửi không thành công do không nhận được Respone", item.SmsOutGUID), "SendSms", ObjectType, AppSetting.WarningType.mt_error, item.CooperateID);
                        }
                        if (logToText)
                        {
                            Log.LogToText(item.SmsOutGUID, result, AppSetting.RouterType.MTROUTER);
                        }
                    }
                    else
                    {
                        //Không tạo được input do lỗi đầu vào
                        SmsOutReportStorage.EnqueueElementData(Key, new SmsOutReportStruct(item.RouterID, item.SmsOutGUID, item.CooperateGUID, DateTime.Now, DateTime.Now, item.RetryOnFailReqTimes, item.RetryOnTimeOutReqTimes, AppSetting.Status.FAIL, threadId));
                        Log.InsertLog(string.Format("[SmsOutGUID = {0}] erorr: {1}", item.SmsOutGUID, strException), "SendSms", ObjectType, AppSetting.WarningType.mt_error, item.CooperateID);
                    }
                }
                catch (Exception ex)
                {
                    HandleException<SmsOutWaiting>(ex, AppSetting.WarningType.mt_error, item);
                }
            }
        }

        private bool CreateXmlOject(SmsOutWaiting item, ref string strObj, ref string strException)
        {
            string bodyPost = "";
            string lable_id = "";
            string template_id = "";
            string agent_id = "";
            string contract_id = "";
            string istelcosub = "";
            if (item.MTTypeID == null) item.MTTypeID = DefaultMTTypeID;
            SmsShortCode itemShortCode = SmsShortCode.FindItem(obj => obj.CooperateID == item.CooperateID && obj.RouterID == item.RouterID && obj.ShortCode == item.ShortCode && obj.OperatorID == item.OperatorID && obj.MTTypeID == item.MTTypeID);
            if (itemShortCode != null)
            {
                //Tìm template tương ứng với message
                SmsTemplate templateMatch = SmsTemplate.FindItem(obj => obj.CooperateID == item.CooperateID && obj.ShortCodeID == itemShortCode.ShortCodeID && Common.RegExpressionValidation("^" + Regex.Replace((obj.FormatTemplate ?? ""), @"\{[0-9]+\}", "(.*?)") + "$", item.Message));
                if (templateMatch != null)
                {
                    string smpp_param = templateMatch.TemplateParameter ?? "";
                    string[] array_param = smpp_param.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                    if (array_param.Length >= 5)
                    {
                        agent_id = array_param[0];//dai ly
                        contract_id = array_param[1];//hop dong
                        template_id = array_param[2]; //id Mau tin (trung voi id tren he thong)
                        lable_id = array_param[3]; //lable_id
                        istelcosub = array_param[4]; //istelcosub
                        //76,72,800,607,0

                        List<string> paramList = ReverseStringFormat(templateMatch.FormatTemplate, item.Message);
                        if (paramList.Count == templateMatch.NumOfParameter)
                        {
                            bodyPost = string.Format("{0}", string.Join("", ((Func<List<string>, IEnumerable<string>>)(list =>
                            {
                                List<string> retList = new List<string>();
                                for (int i = 1; i <= list.Count; i++)
                                {
                                    retList.Add(string.Format(@"<PARAMS><NUM>{0}</NUM><CONTENT>{1}</CONTENT></PARAMS>", i, list[i - 1]));
                                }
                                return retList;
                            }))(paramList)));
                            bodyPost = string.Format(@"
                            <RQST>
                              <name>{0}</name>
                              <REQID>{1}</REQID>
                              <LABELID>{2}</LABELID>
                              <TEMPLATEID>{3}</TEMPLATEID>
                              <ISTELCOSUB>{4}</ISTELCOSUB>
                              {5}
                              <SCHEDULETIME>{6}</SCHEDULETIME>
                              <MOBILELIST>{7}</MOBILELIST>
                              <CONTRACTID>{8}</CONTRACTID>
                              <CONTRACTTYPEID>{9}</CONTRACTTYPEID>
                              <AGENTID>{10}</AGENTID>
                              <APIUSER>{11}</APIUSER>
                              <APIPASS>{12}</APIPASS>
                              <USERNAME>{13}</USERNAME>
                            </RQST>
                            ", "send_sms_list", 1, lable_id, template_id, istelcosub, bodyPost, String.Format("{0:dd/MM/yyyy HH:mm}", DateTime.Now), item.DestAddr, contract_id, item.MTTypeID == 1 ? "2" : "1", agent_id, UserName, Password, UserName);
                        }
                        else
                        {
                            strException = "Tham số không phù hợp: số tham số của Pattern không bằng với NumOfParameter";
                            return false;
                        }
                    }
                    else
                    {
                        strException = "TemplateParameter không phù hợp";
                        return false;
                    }
                }
                else
                {
                    strException = "Không tìm thấy Template phù hợp (Tempate bị null)";
                    return false;
                }
            }
            else
            {
                strException = "Không tìm thấy ShortCode phù hợp (ShortCode bị null)";
                return false;
            }
            strObj = bodyPost.ToNormalString();
            strException = string.Empty;
            return true;
        }

        public void ResponseXMLParser(string xml_response, ref string smsSentType, ref string errorCode, ref string errorDesc)
        {
            try
            {
                using (XmlReader reader = XmlReader.Create(new StringReader(xml_response)))
                {
                    reader.ReadToFollowing("RPLY");
                    reader.MoveToFirstAttribute();
                    smsSentType = reader.Value.Trim();
                    reader.ReadToFollowing("ERROR");
                    errorCode = reader.ReadElementContentAsString().Trim();
                    //reader.ReadToFollowing("ERROR_DESC");
                    errorDesc = reader.ReadElementContentAsString().Trim();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private List<string> ReverseStringFormat(string template, string str)
        {
            string pattern = "^" + Regex.Replace(template, @"\{[0-9]+\}", "(.*?)") + "$";
            Regex r = new Regex(pattern);
            Match m = r.Match(str);
            List<string> ret = new List<string>();
            for (int i = 1; i < m.Groups.Count; i++)
            {
                ret.Add(m.Groups[i].Value);
            }
            return ret;
        }
    }
}
